package org.mcflier.appuntamento.io.driver.rss.torrent;

import java.io.IOException;
import java.net.MalformedURLException;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.gnu.stealthp.rsslib.RSSChannel;
import org.gnu.stealthp.rsslib.RSSException;
import org.gnu.stealthp.rsslib.RSSHandler;
import org.gnu.stealthp.rsslib.RSSItem;
import org.gnu.stealthp.rsslib.RSSParser;
import org.mcflier.appuntamento.core.exception.PropertiesException;
import org.mcflier.appuntamento.data.model.TorrentList;
import org.mcflier.appuntamento.i18n.I18N;
import org.mcflier.appuntamento.i18n.exception.I18NLanguageNotFoundException;
import org.mcflier.appuntamento.io.driver.rss.RssTools;
import org.mcflier.appuntamento.io.exception.RSSConnectionException;
import org.mcflier.appuntamento.io.exception.RSSParsingException;

public class RssPirateBayDriver extends AbstractRssTorrentDriver {
	
	public static final String GUID_TAG				= "guid";
    public static final String CONTENT_LENGTH_TAG	= "contentLength";
    public static final String INFO_HASH_TAG		= "infoHash";
    public static final String MAGNET_URI_TAG		= "magnetURI";

	private TorrentList getList(String link, Timestamp since) throws RSSConnectionException, RSSParsingException{
		RSSHandler handler = new RSSHandler();
		try {
			RSSParser.parseXmlFile(RssTools.getRSSContentFile(link).getAbsolutePath(), handler, false);
			RSSChannel channel = handler.getRSSChannel();
			TorrentList torrentList = new TorrentList(link, channel.getTitle(), link);
			torrentList.setDescription(channel.getDescription());
			try {
				torrentList.setLanguage(I18N.getInstance().createLanguage(channel.getLanguage()));
			} catch (I18NLanguageNotFoundException e) {
				this.logger.warning("The torrent rss language was not retrieved: "+e.getMessage());
			} catch (PropertiesException e) {
				this.logger.warning("Problem while retrieving the torrent rss language: "+e.getMessage());
			}
			torrentList.setPubDate(RssTools.convertToTimestamp(channel.getPubDate()));
			torrentList.setLastBuildDate(RssTools.convertToTimestamp(channel.getLastBuildDate()));

			LinkedList objects = channel.getItems();
			Timestamp pubDate;
			RSSItem item;

			for (Object object : objects) {
				item = (RSSItem)object;
				pubDate = RssTools.convertToTimestamp(item.getPubDate());

				if(pubDate!=null && pubDate.after(since) || pubDate.equals(since)){
					TorrentList.TorrentListItem torrentItem = torrentList.new TorrentListItem(item.getTitle(), item.getComments());
					torrentItem.setPubDate(pubDate);
					torrentItem.setCategory(item.getUnknownField(RSSHandler.CATEGORY_TAG));
					torrentItem.setCreator(String.valueOf(item.getDoublinCoreElements().get(RSSHandler.DC_CREATOR_TAG)));
					torrentItem.setGuid(item.getUnknownField(RssPirateBayDriver.GUID_TAG));
					try {
						torrentItem.setContentLength(Long.valueOf(item.getUnknownField(RssPirateBayDriver.CONTENT_LENGTH_TAG)));
					} catch (NumberFormatException e) {
						this.logger.warning("Element: '"+torrentItem.getTitle()+"' has an invalid content length. Set it to -1");
						torrentItem.setContentLength(-1);
					}
					torrentItem.setInfoHash(item.getUnknownField(RssPirateBayDriver.INFO_HASH_TAG));
					torrentItem.setMagnetUri(item.getUnknownField(RssPirateBayDriver.MAGNET_URI_TAG));

					torrentList.addItem(torrentItem);
				}
			}

			return torrentList;
		} catch (MalformedURLException e) {
			throw new RSSConnectionException("Malformed rss url: "+link, e);
		}  catch (RSSException e) {
			throw new RSSParsingException("Error parsing the rss file: "+link, e);
		} catch (IOException e) {
			throw new RSSConnectionException("Error accessing url content: "+link, e);
		}
	}

	@Override
	public List<TorrentList> getHDTorrents() throws RSSConnectionException, RSSParsingException {
		this.logger.info("Getting HD rss list from Pirate Bay");
		return this.getHDTorrents(new Timestamp(0));
	}

	@Override
	public List<TorrentList> getHDTorrents(Timestamp since) throws RSSConnectionException, RSSParsingException {
		this.logger.info("Getting HD rss list from Pirate Bay since "+since);

		List<TorrentList> torrents = new ArrayList<TorrentList>();
		TorrentList list;
		List<String> hdResources = this.getHDResources();
		for (String resource : hdResources) {
			torrents.add(this.getList(resource, since));
		}

		return torrents;
	}

	@Override
	public List<TorrentList> getSDTorrents() throws RSSConnectionException, RSSParsingException {
		this.logger.info("Getting SD rss list from Pirate Bay");
		return this.getSDTorrents(new Timestamp(0));
	}

	@Override
	public List<TorrentList> getSDTorrents(Timestamp since) throws RSSConnectionException, RSSParsingException {
		this.logger.info("Getting SD rss list from Pirate Bay since "+since);

		List<TorrentList> torrents = new ArrayList<TorrentList>();
		TorrentList list;
		List<String> sdResources = this.getSDResources();
		for (String resource : sdResources) {
			torrents.add(this.getList(resource, since));
		}

		return torrents;
	}
}
